﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
using WebServerX.Utility;

namespace WebServerX
{
    public class Response
    {
        #region Properties

        public Request Request
        {
            get { return _request; }
        }
        private Request _request = null;

        #endregion

        #region Public Methods

        public Response(Request request)
        {
            this._request = request;
        }

        public void Get(NetworkStream ns)
        {
            HttpStatusCode status = HttpStatusCode._200;
            string code = "OK";

            string header = String.Empty;
            ResponseFileData fileData = new ResponseFileData();

            try
            {
                fileData = this.GetFileData(out status, out code);

                header = this.BuildResponseHeader(status, code, fileData);
            }
            catch (Exception ex)
            {
                status = HttpStatusCode._500;
                code = ex.Message;
            }

            string headerLine = this.BuildResponseHeaderLine(status, code) + "\n\r";
            headerLine += header + "\n\r";

            ASCIIEncoding encoding = new ASCIIEncoding();
            byte[] res = encoding.GetBytes(headerLine);

            ns.Write(res, 0, res.Length);

            if(fileData.Data != null)
                ns.Write(fileData.Data, 0, fileData.Data.Length);
        }

        private string BuildResponseHeader(HttpStatusCode status, string code, ResponseFileData fd)
        {
            string header = this.BuildResponseLine(ResponseHeaderKeys.Date, fd) + "\n\r";
            header += this.BuildResponseLine(ResponseHeaderKeys.Server, fd) + "\n\r";
            header += this.BuildResponseLine(ResponseHeaderKeys.ContentType, fd) + "\n\r";
            header += this.BuildResponseLine(ResponseHeaderKeys.LastModified, fd) + "\n\r";
            header += this.BuildResponseLine(ResponseHeaderKeys.ContentLength, fd) + "\n\r";

            return header;
        }

        private string BuildResponseLine(ResponseHeaderKeys key, ResponseFileData fd)
        {
            string line = String.Empty;

            switch (key)
            {
                case ResponseHeaderKeys.Date:
                    line = String.Format("{0}: {1:r}", Text.GetEnumDescription(ResponseHeaderKeys.Date), DateTime.Now);
                    break;
                case ResponseHeaderKeys.Server:
                    line = String.Format("{0}: WebServerX", Text.GetEnumDescription(ResponseHeaderKeys.Server));
                    break;
                case ResponseHeaderKeys.ContentType:
                    line = String.Format("{0}: {1}", Text.GetEnumDescription(ResponseHeaderKeys.ContentType), fd.MIMEType);
                    break;
                case ResponseHeaderKeys.LastModified:
                    line = String.Format("{0}: {1:r}", Text.GetEnumDescription(ResponseHeaderKeys.LastModified), fd.FileInfo.LastWriteTime);
                    break;
                case ResponseHeaderKeys.ContentLength:
                    line = String.Format("{0}: {1}", Text.GetEnumDescription(ResponseHeaderKeys.LastModified), fd.FileInfo.Length);
                    break;
                default:
                    break;
            }

            return line;
        }

        private string BuildResponseHeaderLine(HttpStatusCode status, string code)
        {
            string line = String.Format("{0} {1} {2}", Text.GetEnumDescription(this.Request.HttpVersion),
                Text.GetEnumDescription(status), code);

            return line;
        }

        private ResponseFileData GetFileData(out HttpStatusCode status, out string code)
        {
            ResponseFileData fd = new ResponseFileData();

            status = HttpStatusCode._200;
            code = "OK";

            string baseDir = "C:\\mysite";

            foreach(string s in this.Request.Uri.Segments)
            {
                string dir = s.Replace('/', '\\');
                baseDir += dir;
            }

            FileStream fp = File.Open(baseDir, FileMode.Open);

            fd.Data = new byte[fp.Length];
            fp.Read(fd.Data, 0, (int)fp.Length);

            fp.Close();

            fd.FileInfo = new FileInfo(baseDir);

            fd.MIMEType = Text.GetMIMEType(baseDir);

            return fd;
        }

        #endregion
    }
}
